#pragma once
#include "Common.h"

#define INTERMEDIATE_CODE_DATA_SIZE 0x1000

enum INSTRUCTION_TYPE
{
	IT_ASSIGN_VAR_TO_VAR,
	IT_ASSIGN_CONSTANT_TO_VAR,

	IT_ADD_VAR_TO_VAR,
	IT_ADD_CONSTANT_TO_VAR,

	IT_SUB_VAR_FROM_VAR,
	IT_SUB_CONSTANT_FROM_VAR,

	IT_MUL_VAR_BY_VAR,
	IT_MUL_VAR_BY_CONSTANT,

	IT_DIV_VAR_BY_VAR,
	IT_DIV_VAR_BY_CONSTANT,

	IT_JMP,

	IT_RETURN
};

struct Instruction
{
	enum INSTRUCTION_TYPE type;
};

struct ReturnIns
{
	Int returnCode;
};

struct VarToVarIns
{
	struct Variable* src;
	struct Variable* dest;
};

struct ConstantToVarIns
{
	struct Variable* dest;
	struct Constant src;
};

#define AssignVarToVarIns VarToVarIns
#define AddVarToVarIns VarToVarIns
#define SubVarFromVarIns VarToVarIns
#define MulVarByVarIns VarToVarIns
#define DivVarByVarIns VarToVarIns

#define AssignConstantToVarIns ConstantToVarIns
#define AddConstantToVarIns ConstantToVarIns
#define SubConstantFromVarIns ConstantToVarIns
#define MulVarByConstantIns ConstantToVarIns
#define DivVarByConstantIns ConstantToVarIns

#define ADD_INSTRUCTION(INSTRUCTION_STRUCT, INSTRUCTION_TYPE)\
	PSUB_INSTRUCTION(icode, INSTRUCTION_STRUCT);\
	icode->type = INSTRUCTION_TYPE;\
	icode = ((struct Instruction*)(((Int8*)icode) + (sizeof(INSTRUCTION_STRUCT) + sizeof(struct Instruction))));

#define PSUB_INSTRUCTION(I, SUB) ((SUB*)(((Int8*)(I)) + sizeof(struct Instruction)))

extern UInt8 icodeData[INTERMEDIATE_CODE_DATA_SIZE];
extern struct Instruction* icode;
